"""
文件处理模块
提供文件读取、格式转换和检查等功能
"""

import os
import mimetypes
from typing import Optional, Tuple, List
import chardet
import docx
import fitz  # PyMuPDF
import markdown
from bs4 import BeautifulSoup
from .config import get_config

class FileHandler:
    """文件处理类"""
    
    def __init__(self):
        """初始化文件处理类"""
        # 获取支持的文件格式和最大文件大小
        self.supported_formats = get_config("文档.支持格式", ["txt", "pdf", "docx", "md", "html"])
        self.max_file_size = get_config("文档.最大大小", 10 * 1024 * 1024)  # 默认10MB
        
        # 注册MIME类型
        self._register_mime_types()
    
    def _register_mime_types(self) -> None:
        """注册自定义MIME类型"""
        mimetypes.add_type('text/markdown', '.md')
        mimetypes.add_type('text/plain', '.txt')
    
    def check_file(self, file_path: str) -> Tuple[bool, Optional[str]]:
        """
        检查文件是否可以处理
        
        Args:
            file_path: 文件路径
            
        Returns:
            Tuple[bool, Optional[str]]: (是否可以处理, 错误信息)
        """
        # 检查文件是否存在
        if not os.path.exists(file_path):
            return False, "文件不存在"
        
        # 检查文件大小
        file_size = os.path.getsize(file_path)
        if file_size > self.max_file_size:
            return False, f"文件大小超过限制（{self.max_file_size / 1024 / 1024}MB）"
        
        # 检查文件格式
        ext = os.path.splitext(file_path)[1].lower().lstrip('.')
        if ext not in self.supported_formats:
            return False, "不支持的文件格式"
        
        return True, None
    
    def read_file(self, file_path: str) -> Tuple[Optional[str], Optional[str]]:
        """
        读取文件内容
        
        Args:
            file_path: 文件路径
            
        Returns:
            Tuple[Optional[str], Optional[str]]: (文件内容, 错误信息)
        """
        # 检查文件
        can_process, error = self.check_file(file_path)
        if not can_process:
            return None, error
        
        try:
            ext = os.path.splitext(file_path)[1].lower()
            
            # 根据文件扩展名选择相应的处理方法
            if ext == '.txt':
                return self._read_text_file(file_path), None
            elif ext == '.pdf':
                return self._read_pdf_file(file_path), None
            elif ext == '.docx':
                return self._read_docx_file(file_path), None
            elif ext == '.md':
                return self._read_markdown_file(file_path), None
            elif ext == '.html':
                return self._read_html_file(file_path), None
            else:
                return None, "不支持的文件格式"
                
        except Exception as e:
            return None, f"读取文件失败：{str(e)}"
    
    def _read_text_file(self, file_path: str) -> str:
        """
        读取文本文件
        
        Args:
            file_path: 文件路径
            
        Returns:
            str: 文件内容
        """
        # 首先读取文件的二进制内容
        with open(file_path, 'rb') as f:
            raw_data = f.read()
        
        # 检测编码
        result = chardet.detect(raw_data)
        encoding = result['encoding'] or 'utf-8'
        
        # 使用检测到的编码读取文件
        with open(file_path, 'r', encoding=encoding) as f:
            return f.read()
    
    def _read_pdf_file(self, file_path: str) -> str:
        """
        读取PDF文件
        
        Args:
            file_path: 文件路径
            
        Returns:
            str: 文件内容
        """
        text = []
        
        # 打开PDF文件
        with fitz.open(file_path) as doc:
            # 遍历每一页
            for page in doc:
                # 提取文本
                text.append(page.get_text())
        
        return '\n'.join(text)
    
    def _read_docx_file(self, file_path: str) -> str:
        """
        读取DOCX文件
        
        Args:
            file_path: 文件路径
            
        Returns:
            str: 文件内容
        """
        text = []
        
        # 打开DOCX文件
        doc = docx.Document(file_path)
        
        # 提取段落文本
        for para in doc.paragraphs:
            if para.text.strip():
                text.append(para.text)
        
        return '\n'.join(text)
    
    def _read_markdown_file(self, file_path: str) -> str:
        """
        读取Markdown文件
        
        Args:
            file_path: 文件路径
            
        Returns:
            str: 文件内容
        """
        # 读取文件内容
        with open(file_path, 'r', encoding='utf-8') as f:
            md_content = f.read()
        
        # 将Markdown转换为HTML
        html_content = markdown.markdown(md_content)
        
        # 使用BeautifulSoup提取纯文本
        soup = BeautifulSoup(html_content, 'html.parser')
        return soup.get_text()
    
    def _read_html_file(self, file_path: str) -> str:
        """
        读取HTML文件
        
        Args:
            file_path: 文件路径
            
        Returns:
            str: 文件内容
        """
        # 读取文件内容
        with open(file_path, 'r', encoding='utf-8') as f:
            html_content = f.read()
        
        # 使用BeautifulSoup提取纯文本
        soup = BeautifulSoup(html_content, 'html.parser')
        
        # 移除script和style标签
        for script in soup(["script", "style"]):
            script.decompose()
        
        return soup.get_text()
    
    def get_supported_formats(self) -> List[str]:
        """
        获取支持的文件格式列表
        
        Returns:
            List[str]: 支持的文件格式列表
        """
        return self.supported_formats
    
    def get_max_file_size(self) -> int:
        """
        获取最大文件大小限制
        
        Returns:
            int: 最大文件大小（字节）
        """
        return self.max_file_size
    
    def set_max_file_size(self, size: int) -> None:
        """
        设置最大文件大小限制
        
        Args:
            size: 最大文件大小（字节）
        """
        self.max_file_size = size
    
    def add_supported_format(self, format: str) -> bool:
        """
        添加支持的文件格式
        
        Args:
            format: 文件格式（不含点号）
            
        Returns:
            bool: 是否添加成功
        """
        format = format.lower().strip()
        if format and format not in self.supported_formats:
            self.supported_formats.append(format)
            return True
        return False
    
    def remove_supported_format(self, format: str) -> bool:
        """
        移除支持的文件格式
        
        Args:
            format: 文件格式（不含点号）
            
        Returns:
            bool: 是否移除成功
        """
        format = format.lower().strip()
        if format in self.supported_formats:
            self.supported_formats.remove(format)
            return True
        return False

# 创建全局实例
file_handler = FileHandler()

def init_file_handler() -> FileHandler:
    """
    初始化全局文件处理实例
    
    Returns:
        FileHandler: 文件处理实例
    """
    global file_handler
    file_handler = FileHandler()
    return file_handler

def read_file(file_path: str) -> Tuple[Optional[str], Optional[str]]:
    """
    读取文件的快捷方法
    
    Args:
        file_path: 文件路径
        
    Returns:
        Tuple[Optional[str], Optional[str]]: (文件内容, 错误信息)
    """
    return file_handler.read_file(file_path)

def check_file(file_path: str) -> Tuple[bool, Optional[str]]:
    """
    检查文件的快捷方法
    
    Args:
        file_path: 文件路径
        
    Returns:
        Tuple[bool, Optional[str]]: (是否可以处理, 错误信息)
    """
    return file_handler.check_file(file_path)

def get_supported_formats() -> List[str]:
    """
    获取支持的文件格式的快捷方法
    
    Returns:
        List[str]: 支持的文件格式列表
    """
    return file_handler.get_supported_formats()

def get_max_file_size() -> int:
    """
    获取最大文件大小的快捷方法
    
    Returns:
        int: 最大文件大小（字节）
    """
    return file_handler.get_max_file_size()